package cn.edward.camp.server.controller;

import cn.edward.camp.core.RpcRequest;
import cn.edward.camp.core.RpcResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.stream.Stream;

@RestController
public class RpcController {

    @Autowired
    ApplicationContext context;

    @PostMapping(value = "/rpc",
            consumes = {MediaType.APPLICATION_JSON_VALUE},
            produces = {MediaType.APPLICATION_JSON_VALUE})
    public RpcResponse rpc(@RequestBody RpcRequest rpcRequest) {
        try {
            Object service = context.getBean(rpcRequest.getService());
            Method method = resolveMethod(service.getClass(), rpcRequest.getMethod());
            RpcResponse response = new RpcResponse();
            response.setStatus(true);
            Object result = method.invoke(service, rpcRequest.getParams());
            response.setResult(JSON.toJSONString(result, SerializerFeature.WriteClassName));
            return response;
        } catch (InvocationTargetException | IllegalAccessException e) {
            e.printStackTrace();
            RpcResponse response = new RpcResponse();
            response.setStatus(false);
            response.setException(e);
            return response;
        }
    }

    private Method resolveMethod(Class<?> clazz, String methodName) {
        return Stream.of(clazz.getDeclaredMethods()).filter(m -> m.getName().equals(methodName)).findFirst().get();
    }
}
